package com.tsd.common.controller;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.tsd.core.storage.AliyunStorage;
import com.tsd.core.utils.HlpUtils;
import com.tsd.core.vo.HttpResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 描述：CommonFile文件表 控制层
 * 文件上传分为4种模式：
 * 1）直接使用form上传  uploadFile.action
 * 2）切片Form上传  uploadFormFileSlice.action
 * 3）转为base64上传  uploadFileBase64.action
 * 4）切片base64上传 uploadFileBase64Slice.action
 *
 * @author huawei
 * @date 2021/08/08 20:40:38
 */
@Controller
@Scope("prototype")
@RequestMapping("/anon")
@Api(tags = "阿里云访问OSS的临时令牌", description = "")
public class AliyunStsController extends BaseController {

    static AssumeRoleResponse.Credentials credentials;
    static long expiredTime = 0;
    final static long minutes5 = 300 * 1000;

    @Resource
    AliyunStorage aliyunStorage;

    @ApiOperation(value = "获取阿里云临时令牌")
    @ResponseBody
    @RequestMapping(value = "/getAliyunSts.action")
    synchronized public Map<String, String> getAliyunSts() {
        Map<String, String> respMap = new LinkedHashMap<>();
        // STS接入地址，例如sts.cn-hangzhou.aliyuncs.com。
        String endpoint = aliyunStorage.getStsEndpoint();
        //"sts.cn-guangzhou.aliyuncs.com";
        // 填写步骤1生成的访问密钥AccessKey ID和AccessKey Secret。
        String AccessKeyId = aliyunStorage.getAccessKeyId();
        String accessKeySecret = aliyunStorage.getAccessKeySecret();
        // 填写步骤3获取的角色ARN。
        String roleArn = aliyunStorage.getRoleArn();
        // "acs:ram::113.....0750:role/ramosstest";
        // 自定义角色会话名称，用来区分不同的令牌，例如可填写为SessionTest。
        String roleSessionName = "SessionTest";
        // 以下Policy用于限制仅允许使用临时访问凭证向目标存储空间examplebucket上传文件。
        // 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集，即仅允许将文件上传至目标存储空间examplebucket下的exampledir目录。
        String policy = "{\n" +
                "    \"Version\": \"1\", \n" +
                "    \"Statement\": [\n" +
                "        {\n" +
                "            \"Action\": [\n" +
                "                \"oss:PutObject\"\n" +
                "            ], \n" +
                "            \"Resource\": [\n" +
                "                \"acs:oss:*:*:examplebucket/*\" \n" +
                "            ], \n" +
                "            \"Effect\": \"Allow\"\n" +
                "        }\n" +
                "    ]\n" +
                "}";
        try {
            // regionId表示RAM的地域ID。以华东1（杭州）地域为例，regionID填写为cn-hangzhou。也可以保留默认值，默认值为空字符串（""）。
            String regionId = "";
            // 添加endpoint。适用于Java SDK 3.12.0及以上版本。
            DefaultProfile.addEndpoint(regionId, "Sts", endpoint);
            // 添加endpoint。适用于Java SDK 3.12.0以下版本。
            // DefaultProfile.addEndpoint("",regionId, "Sts", endpoint);
            // 构造default profile。
            IClientProfile profile = DefaultProfile.getProfile(regionId, AccessKeyId, accessKeySecret);
            // 构造client。
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            // 适用于Java SDK 3.12.0及以上版本。
            request.setSysMethod(MethodType.POST);
            // 适用于Java SDK 3.12.0以下版本。
            //request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(null); // 如果policy为空，则用户将获得该角色下所有权限。
            long durationSec = 3600L;
            request.setDurationSeconds(3600L); // 设置临时访问凭证的有效时间为3600秒。
            boolean hasExpired = credentials == null || expiredTime - System.currentTimeMillis() < minutes5;
            if (hasExpired) {
                final AssumeRoleResponse stsResponse = client.getAcsResponse(request);
                credentials = stsResponse.getCredentials();
                expiredTime = System.currentTimeMillis() + durationSec * 1000;
            }
            long remainSec = (expiredTime - System.currentTimeMillis()) / 1000;
            respMap.put("StatusCode", "200");
            respMap.put("bucketName", aliyunStorage.getBucketName());
            respMap.put("ossEndpoint", aliyunStorage.getEndpoint());
            respMap.put("bindDomain", aliyunStorage.getBindDomain());
            respMap.put("time", HlpUtils.date2String(new Date(), HlpUtils.Format_Yyyy_MM_dd_HH_mm_ss));
            respMap.put("AccessKeyId", credentials.getAccessKeyId());
            respMap.put("AccessKeySecret", credentials.getAccessKeySecret());
            respMap.put("SecurityToken", credentials.getSecurityToken());
            respMap.put("Expiration", String.valueOf(remainSec));
            respMap.put("region", profile.getRegionId());
            respMap.put("expiredTime", String.valueOf(expiredTime));
        } catch (ClientException e) {
            respMap.put("StatusCode", "500");
            respMap.put("ErrorCode", e.getErrCode());
            respMap.put("ErrorMessage", e.getErrMsg());
        }
        return respMap;
    }

    @ApiOperation(value = "web端获取阿里云oss STS")
    @ResponseBody
    @RequestMapping(value = "/getAliyunSts4Web.action")
    public HttpResult<Object> getAliyunSts4Web() {
        return HttpResult.success(getAliyunSts());
    }
}
